Imports System
Imports System.IO
Imports System.Text
Imports System.Web

Imports ICSharpCode.SharpZipLib.Zip

Imports Krystalware.SlickUpload
Imports Krystalware.SlickUpload.Configuration
Imports Krystalware.SlickUpload.Storage

Namespace Storage
    Public Class ZipUploadStreamProvider
        Inherits UploadStreamProviderBase

        Private _location As String

        Public Sub New(settings As UploadStreamProviderElement)
            MyBase.New(settings)

            _location = Settings.Parameters("location")

            If String.IsNullOrEmpty(_location) Then
                _location = "~/Files/"
            End If
        End Sub

        Public Overrides Function GetReadStream(ByVal f As Krystalware.SlickUpload.UploadedFile) As System.IO.Stream
            Dim fileS As FileStream = Nothing
            Dim zipS As ZipInputStream = Nothing

            Try
                fileS = File.OpenRead(f.ServerLocation)
                zipS = New ZipInputStream(fileS)

                zipS.GetNextEntry()

                Return zipS
            Catch
                If Not zipS Is Nothing Then
                    zipS.Dispose()
                End If

                If Not fileS Is Nothing Then
                    fileS.Dispose()
                End If

                Throw
            End Try
        End Function

        Public Overrides Function GetWriteStream(ByVal f As Krystalware.SlickUpload.UploadedFile) As System.IO.Stream
            f.ServerLocation = path.Combine(HttpContext.Current.Server.MapPath(_location), path.GetFileNameWithoutExtension(GetValidFileName(f.ClientName)) + ".zip")

            Directory.CreateDirectory(Path.GetDirectoryName(f.ServerLocation))

            Dim fileS As FileStream = Nothing
            Dim zipS As ZipOutputStream = Nothing

            Try
                fileS = File.OpenWrite(f.ServerLocation)
                zipS = New ZipOutputStream(fileS)

                zipS.SetLevel(5)

                zipS.PutNextEntry(New ZipEntry(f.ClientName))

                Return zipS
            Catch
                If Not zipS Is Nothing Then
                    zipS.Dispose()
                End If

                If Not fileS Is Nothing Then
                    fileS.Dispose()
                End If

                Throw
            End Try
        End Function

        Public Overrides Sub RemoveOutput(ByVal f As Krystalware.SlickUpload.UploadedFile)
            If File.Exists(f.ServerLocation) Then
                File.Delete(f.ServerLocation)
            End If
        End Sub

        Function GetValidFileName(fileName As String) As String
            Dim validFileName As StringBuilder = New StringBuilder(fileName)

            For Each invalidChar As Char In Path.GetInvalidFileNameChars()
                validFileName.Replace(invalidChar, "-"c)
            Next invalidChar

            Return validFileName.ToString()
        End Function
    End Class
End Namespace